﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace slnes
{
    using System.IO;
    using Exceptions;

    public partial class GameField : UserControl
    {
        internal bool fps;
        internal AppletUI gui;
        public bool isActiveVar = true;
        internal NES nes;
        internal ScreenView panelScreen;
        internal string rom = "3.nes";
        internal bool scale;
        internal bool scanlines;
        internal bool sound = true;
        private bool started;
        internal bool stereo = true;
        private FrameworkElement keyHandler;

        public GameField()
        {
            InitializeComponent();
            
        }


        public static DependencyProperty FrameRateProperty = DependencyProperty.Register("FrameRate",typeof(int), typeof(GameField), new PropertyMetadata(FrameRateChanged));
        private int framerate = 50;
        private Stream audioStream;

        private static void FrameRateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((GameField) d).SetFrameRate((int) e.NewValue);
        }

        private void SetFrameRate(int frameRate)
        {
            this.framerate = frameRate;
            SetNesFrameRate();
        }

        private void SetNesFrameRate()
        {
            if (nes!=null)
            {
                Application.Current.Host.Settings.MaxFrameRate = framerate;
                nes.Framerate = framerate;
            }
        }

        public int FrameRate
        {
            get
            {
                return (int) GetValue(FrameRateProperty);
            }
            set
            {
                SetValue(FrameRateProperty, value);
            }
        }



        public bool Started
        {
            get { return started; }
        }

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            base.Focus();
            Application.Current.Host.Settings.EnableFrameRateCounter = true;
        }

        public void LoadRom(Stream stream)
        {
            this.gui = new AppletUI(this);
            this.gui.init(false);
            Globals.memoryFlushValue = 0;
            this.nes = this.gui.NES;
            this.nes.enableSound(this.sound);
            this.nes.reset();
            this.renderImage.Source = this.nes.gui.ScreenView.Image;
            //nes.stateSave();
            SetNesFrameRate();
            this.nes.loadRom(stream);
            if (this.nes.rom.Valid)
            {
                this.nes.Cpu.Run();
            }
            else
            {
                throw new InvalidRomException();
            }
            nes.papu.line.SetSaveStream(audioStream);
            this.mediaElement.SetSource(this.nes.papu.line);
            this.started = true;
            CompositionTarget.Rendering += (new EventHandler(this.CompositionTarget_Rendering));
            InitKeyHandlers();
            base.Focus();
        }

        private void InitKeyHandlers()
        {


            DependencyObject parent = Parent;
            do
            {
                FrameworkElement root = parent as FrameworkElement;
                if (root != null)
                {
                    if (root.Parent == null)
                    {
                        root.KeyDown += nes.gui.Joy1.keyPressed;
                        root.KeyUp += nes.gui.Joy1.keyReleased;
                        root.KeyDown += nes.gui.Joy2.keyPressed;
                        root.KeyUp += nes.gui.Joy2.keyReleased;
                        keyHandler = root;
                        break;
                    }

                    parent = root.Parent;
                }
            }
            while (true);
        }

        private void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            if ((this.nes != null) && (this.nes.cpu != null))
            {
                this.nes.cpu.emulate();
                this.nes.gui.ScreenView.Image.Invalidate();
            }
        }

        public void SetAudioSave(Stream stream)
        {
            audioStream = stream;
        }
    }
}
